package com.powerbank.user.service.impl;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.powerbank.common.entity.*;
import com.powerbank.common.exception.BusinessException;
import com.powerbank.common.result.ResultCode;
import com.powerbank.user.dto.CreatePaymentDTO;
import com.powerbank.user.mapper.*;
import com.powerbank.user.service.DepositService;
import com.powerbank.user.service.PaymentService;
import com.powerbank.user.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 押金管理服务实现类
 */
@Slf4j
@Service
public class DepositServiceImpl implements DepositService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private UserIdentityMapper userIdentityMapper;

    @Autowired
    private PaymentRecordMapper paymentRecordMapper;

    @Autowired
    private RentalOrderMapper rentalOrderMapper;

    @Autowired
    private PaymentService paymentService;

    // 默认押金金额配置
    private static final BigDecimal DEFAULT_DEPOSIT_AMOUNT = new BigDecimal("99.00");
    private static final BigDecimal ADVANCED_USER_DEPOSIT_AMOUNT = new BigDecimal("0.00"); // 高级认证用户免押金

    @Override
    public BigDecimal calculateDepositAmount(Long userId) {
        log.info("计算用户{}押金金额", userId);

        // 1. 检查用户认证等级
        UserIdentity identity = getUserIdentity(userId);
        
        if (identity != null && identity.getVerifyStatus() == 1) {
            // 已通过实名认证
            if (identity.getVerifyLevel() >= 2) {
                // 中级以上认证用户免押金
                log.info("用户{}为{}级认证用户，免押金", userId, identity.getVerifyLevel());
                return ADVANCED_USER_DEPOSIT_AMOUNT;
            }
        }

        // 2. TODO: 可以根据用户信用分、历史记录等调整押金金额
        // 3. TODO: 可以根据节假日、促销活动等调整押金金额

        log.info("用户{}需要支付押金: {}", userId, DEFAULT_DEPOSIT_AMOUNT);
        return DEFAULT_DEPOSIT_AMOUNT;
    }

    @Override
    public boolean needPayDeposit(Long userId) {
        BigDecimal depositAmount = calculateDepositAmount(userId);
        return depositAmount.compareTo(BigDecimal.ZERO) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public PaymentResultVO createDepositPayment(Long userId, Long orderId, String paymentMethod) {
        log.info("为用户{}创建押金支付订单 - 订单ID: {}, 支付方式: {}", userId, orderId, paymentMethod);

        // 1. 验证订单存在且属于当前用户
        RentalOrder order = validateOrderOwnership(userId, orderId);

        // 2. 检查是否已有押金支付记录
        checkExistingDepositPayment(orderId);

        // 3. 计算押金金额
        BigDecimal depositAmount = calculateDepositAmount(userId);
        if (depositAmount.compareTo(BigDecimal.ZERO) <= 0) {
            throw new BusinessException(ResultCode.PARAM_ERROR.getCode(), "当前用户无需支付押金");
        }

        // 4. 创建支付订单
        CreatePaymentDTO paymentDTO = new CreatePaymentDTO();
        paymentDTO.setOrderId(orderId);
        paymentDTO.setPaymentType("DEPOSIT");
        paymentDTO.setPaymentMethod(paymentMethod);
        paymentDTO.setPaymentAmount(depositAmount);
        paymentDTO.setRemark("充电宝租借押金");

        return paymentService.createPayment(userId, paymentDTO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public DepositRefundResultVO processDepositRefund(Long userId, Long orderId, BigDecimal feeAmount, String refundReason) {
        log.info("处理用户{}押金退还 - 订单ID: {}, 扣除费用: {}", userId, orderId, feeAmount);

        // 1. 验证订单
        RentalOrder order = validateOrderOwnership(userId, orderId);
        if (order.getOrderStatus() != 2) { // 必须是已归还状态
            throw new BusinessException(ResultCode.ORDER_STATUS_ERROR.getCode(), "订单状态不正确，无法退还押金");
        }

        // 2. 查找押金支付记录
        LambdaQueryWrapper<PaymentRecord> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(PaymentRecord::getOrderId, orderId)
                .eq(PaymentRecord::getPaymentType, "DEPOSIT")
                .eq(PaymentRecord::getPaymentStatus, 1); // 已支付
        PaymentRecord depositRecord = paymentRecordMapper.selectOne(wrapper);

        if (depositRecord == null) {
            throw new BusinessException(ResultCode.PARAM_ERROR.getCode(), "未找到押金支付记录");
        }

        // 3. 计算退还金额
        BigDecimal actualRefundAmount = depositRecord.getActualAmount().subtract(feeAmount);
        if (actualRefundAmount.compareTo(BigDecimal.ZERO) < 0) {
            actualRefundAmount = BigDecimal.ZERO;
        }

        // 4. 处理退款
        DepositRefundResultVO result = new DepositRefundResultVO();
        result.setRefundNo("REF" + System.currentTimeMillis() + RandomUtil.randomLong(1000, 9999));
        result.setOrderId(orderId);
        result.setOrderNo(order.getOrderNo());
        result.setOriginalDepositAmount(depositRecord.getActualAmount());
        result.setFeeAmount(feeAmount);
        result.setActualRefundAmount(actualRefundAmount);
        result.setRefundReason(refundReason);
        result.setRefundTime(LocalDateTime.now());

        if (actualRefundAmount.compareTo(BigDecimal.ZERO) > 0) {
            // 执行退款
            boolean refundSuccess = paymentService.applyRefund(
                    userId, 
                    depositRecord.getPaymentNo(), 
                    actualRefundAmount, 
                    refundReason
            );

            if (refundSuccess) {
                result.setRefundStatus("SUCCESS");
                result.setRefundMethod("ORIGINAL"); // 原路返回
                result.setEstimatedArrivalTime(LocalDateTime.now().plusDays(3)); // 预计3天到账
                result.setRemark("押金退还成功");
                log.info("押金退还成功 - 订单: {}, 退还金额: {}", orderId, actualRefundAmount);
            } else {
                result.setRefundStatus("FAILED");
                result.setRemark("押金退还失败");
                log.error("押金退还失败 - 订单: {}", orderId);
            }
        } else {
            result.setRefundStatus("SUCCESS");
            result.setRefundMethod("FEE_DEDUCTION");
            result.setRemark("押金已全部用于支付费用");
            log.info("押金全部用于支付费用 - 订单: {}", orderId);
        }

        return result;
    }

    @Override
    public PageResult<DepositRecordVO> getUserDepositRecords(Long userId, int page, int size) {
        log.info("查询用户{}押金记录 - 页码: {}, 页大小: {}", userId, page, size);

        Page<PaymentRecord> pageParam = new Page<>(page, size);
        LambdaQueryWrapper<PaymentRecord> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(PaymentRecord::getUserId, userId)
                .eq(PaymentRecord::getPaymentType, "DEPOSIT")
                .orderByDesc(PaymentRecord::getCreatedTime);

        Page<PaymentRecord> result = paymentRecordMapper.selectPage(pageParam, wrapper);

        List<DepositRecordVO> records = result.getRecords().stream()
                .map(this::convertToDepositRecordVO)
                .collect(Collectors.toList());

        return new PageResult<>(records, result.getTotal(), (int) result.getCurrent(), (int) result.getSize());
    }

    @Override
    public DepositSummaryVO getUserDepositSummary(Long userId) {
        log.info("获取用户{}押金统计信息", userId);

        DepositSummaryVO summary = new DepositSummaryVO();
        summary.setUserId(userId);

        // 1. 获取用户认证信息
        UserIdentity identity = getUserIdentity(userId);
        if (identity != null) {
            summary.setVerifyLevel(identity.getVerifyLevel());
            summary.setDepositFree(identity.getVerifyLevel() >= 2);
            summary.setDepositFreeReason(identity.getVerifyLevel() >= 2 ? "中级以上认证用户免押金" : null);
        } else {
            summary.setVerifyLevel(0);
            summary.setDepositFree(false);
        }

        // 2. 统计押金支付记录
        LambdaQueryWrapper<PaymentRecord> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(PaymentRecord::getUserId, userId)
                .eq(PaymentRecord::getPaymentType, "DEPOSIT");

        List<PaymentRecord> depositRecords = paymentRecordMapper.selectList(wrapper);

        BigDecimal totalPaid = BigDecimal.ZERO;
        BigDecimal totalRefunded = BigDecimal.ZERO;
        int paymentCount = 0;
        int refundCount = 0;

        for (PaymentRecord record : depositRecords) {
            if (record.getPaymentStatus() == 1) { // 已支付
                totalPaid = totalPaid.add(record.getActualAmount());
                paymentCount++;
            }
            if (record.getRefundAmount() != null && record.getRefundAmount().compareTo(BigDecimal.ZERO) > 0) {
                totalRefunded = totalRefunded.add(record.getRefundAmount());
                refundCount++;
            }
        }

        summary.setTotalPaidDeposit(totalPaid);
        summary.setTotalRefundedDeposit(totalRefunded);
        summary.setDepositPaymentCount(paymentCount);
        summary.setDepositRefundCount(refundCount);

        // 3. 计算当前押金状态
        summary.setCurrentDepositAmount(totalPaid.subtract(totalRefunded));
        summary.setFrozenDepositAmount(BigDecimal.ZERO); // TODO: 根据正在进行的订单计算
        summary.setAvailableDepositAmount(summary.getCurrentDepositAmount());

        // 4. 检查是否有正在进行的订单
        LambdaQueryWrapper<RentalOrder> orderWrapper = new LambdaQueryWrapper<>();
        orderWrapper.eq(RentalOrder::getUserId, userId)
                .eq(RentalOrder::getOrderStatus, 1); // 租借中
        long activeOrderCount = rentalOrderMapper.selectCount(orderWrapper);
        summary.setHasActiveOrder(activeOrderCount > 0);

        return summary;
    }

    /**
     * 验证订单所有权
     */
    private RentalOrder validateOrderOwnership(Long userId, Long orderId) {
        RentalOrder order = rentalOrderMapper.selectById(orderId);
        if (order == null) {
            throw new BusinessException(ResultCode.ORDER_NOT_EXIST);
        }

        if (!order.getUserId().equals(userId)) {
            throw new BusinessException(ResultCode.PERMISSION_DENIED);
        }

        return order;
    }

    /**
     * 检查是否已有押金支付记录
     */
    private void checkExistingDepositPayment(Long orderId) {
        LambdaQueryWrapper<PaymentRecord> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(PaymentRecord::getOrderId, orderId)
                .eq(PaymentRecord::getPaymentType, "DEPOSIT")
                .in(PaymentRecord::getPaymentStatus, 0, 1); // 待支付或已支付

        long count = paymentRecordMapper.selectCount(wrapper);
        if (count > 0) {
            throw new BusinessException(ResultCode.PARAM_ERROR.getCode(), "该订单已存在押金支付记录");
        }
    }

    /**
     * 获取用户认证信息
     */
    private UserIdentity getUserIdentity(Long userId) {
        LambdaQueryWrapper<UserIdentity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserIdentity::getUserId, userId);
        return userIdentityMapper.selectOne(wrapper);
    }

    /**
     * 转换为押金记录VO
     */
    private DepositRecordVO convertToDepositRecordVO(PaymentRecord record) {
        DepositRecordVO vo = new DepositRecordVO();
        vo.setId(record.getId());
        vo.setPaymentNo(record.getPaymentNo());
        vo.setOrderId(record.getOrderId());
        vo.setOrderNo(record.getOrderNo());
        vo.setDepositAmount(record.getActualAmount());
        vo.setPaymentMethod(record.getPaymentMethod());
        vo.setPaymentMethodDesc(getPaymentMethodDesc(record.getPaymentMethod()));
        vo.setPaymentStatus(record.getPaymentStatus());
        vo.setPaymentStatusDesc(getPaymentStatusDesc(record.getPaymentStatus()));
        vo.setPaymentTime(record.getPaymentTime());
        vo.setRefundAmount(record.getRefundAmount());
        vo.setRefundTime(record.getRefundTime());
        vo.setCreatedTime(record.getCreatedTime());

        return vo;
    }

    /**
     * 获取支付方式描述
     */
    private String getPaymentMethodDesc(String paymentMethod) {
        switch (paymentMethod) {
            case "WECHAT":
                return "微信支付";
            case "ALIPAY":
                return "支付宝";
            case "WALLET":
                return "钱包支付";
            case "BANK_CARD":
                return "银行卡";
            default:
                return "未知";
        }
    }

    /**
     * 获取支付状态描述
     */
    private String getPaymentStatusDesc(Integer paymentStatus) {
        switch (paymentStatus) {
            case 0:
                return "待支付";
            case 1:
                return "支付成功";
            case 2:
                return "支付失败";
            case 3:
                return "已取消";
            case 4:
                return "已退款";
            default:
                return "未知状态";
        }
    }
}